home *** CD-ROM | disk | FTP | other *** search
Modula Implementation | 1997-04-25 | 9.5 KB | 315 lines | [TEXT/3PRM] |
- implementation module MineTypes
-
- import StdInt, StdMisc, StdBool, StdString, StdList, StdTuple, StdEnum, StdFile
- import deltaPicture, deltaFont, deltaWindow, deltaSystem
- import Random
-
- :: Minefield :== [[Spot]]
- :: Spot = Mine Visibility
- | Empty Int Visibility
- :: Visibility = Visible
- | Invisible
- :: Pebbles :== [Position]
- :: Position :== (!Int,!Int)
- :: Dimension :== (!Int,!Int)
- :: Time = Running Int
- | Off
- :: BestTimes :== (ThreeBest, ThreeBest, ThreeBest)
- :: ThreeBest :== (String,Int,String,Int,String,Int)
-
- :: *MinesBest :== (Files, BestTimes)
-
- EasyDim :== (8, 8)
- EasyMines :== 10
- InterDim :== (16,16)
- InterMines :== 40
- HardDim :== (30,16)
- HardMines :== 99
-
- SizeArea :== 14
-
- GetTime :: !Time -> Int
- GetTime (Running time) = time
- GetTime _ = 0
-
- /* Drawing functions:
- */
-
- DrawCorrectnessPebble :: Pebbles Position !Spot !Picture -> Picture
- DrawCorrectnessPebble _ _ (Mine _) picture
- = picture
- DrawCorrectnessPebble pebble pos _ picture
- | not (isMember pos pebble) = picture
- # picture = SetPenSize (2,2) picture
- picture = MovePenTo base picture
- picture = LinePen (neg_size,neg_size) picture
- picture = MovePen (size,0) picture
- picture = LinePen (neg_size,size) picture
- picture = SetPenNormal picture
- | otherwise = picture
- where
- base = ScaleVector size pos
- size = SizeArea
- neg_size = ~size
-
- DrawNrMines :: !Font !Int !Dimension !Picture -> Picture
- DrawNrMines font nr_mines dim=:(col,row) picture
- # picture = EraseRectangle (base_rect, (x_max, 0)) picture
- picture = MovePenTo base_text picture
- picture = DrawString text picture
- = picture
- where
- base_rect = TranslatePoint base_text (0,descent)
- base_text = ScaleVector SizeArea (col+1,1)
- (_,(x_max,_)) = WindowPictDomain dim
- (_,descent,_,_) = FontMetrics font
- text = "Mines: "+++toString nr_mines
-
- DrawTime :: !Font !Int !Dimension !Picture -> Picture
- DrawTime font time (col,row) picture
- # picture = EraseRectangle (base_rect, base_rect`) picture
- picture = MovePenTo base_text picture
- picture = DrawString text picture
- = picture
- where
- base_text = ScaleVector SizeArea (col+1,row)
- base_rect` = TranslatePoint base_rect (string_width, ~string_height)
- base_rect = TranslatePoint base_text (0, descent)
- string_height = ascent+descent+leading
- string_width = FontStringWidth text font
- (ascent,descent,_,leading) = FontMetrics font
- text = "Time: "+++toString time
-
- DrawPebble :: !Position !Picture -> Picture
- DrawPebble position picture
- = DrawCircle circle (EraseCircle circle picture)
- where
- circle = CirclePosition position
-
- DrawEmptyArea :: !Position !Picture -> Picture
- DrawEmptyArea (x,y) picture
- # picture = SetPenColour (RGB 0.45 0.7 0.45) picture
- picture = FillRectangle (base1,base2) picture
- picture = SetPenColour BlackColour picture
- = picture
- where
- base = ScaleVector size (x-1, y)
- base1 = TranslatePoint base (1,-1)
- base2 = TranslatePoint base (TranslatePoint (size,~size) (-2,2))
- size = SizeArea
-
- DrawSpot :: !Position !Spot !Picture -> Picture
- DrawSpot (x,y) (Empty n Visible) picture
- # picture = EraseRectangle (base1,base2) picture
- | n==0 = picture
- # picture = MovePenTo basenr picture
- picture = DrawString (toString n) picture
- | otherwise = picture
- where
- base = ScaleVector size (x-1, y)
- base1 = TranslatePoint base (1,-1)
- base2 = TranslatePoint base (TranslatePoint (size,~size) (-1,1))
- basenr = TranslatePoint base (2,-2)
- size = SizeArea
- DrawSpot pos=:(x,y) (Mine Visible) picture
- # picture = EraseRectangle (base1,base2) picture
- picture = FillCircle (CirclePosition pos) picture
- = picture
- where
- base = ScaleVector size (x-1,y)
- base1 = TranslatePoint base (1,-1)
- base2 = TranslatePoint base (TranslatePoint (size,~size) (-1,1))
- size = SizeArea
- DrawSpot pos _ picture
- = DrawEmptyArea pos picture
-
- DrawAnySpot :: !Position !Spot !Picture -> Picture
- DrawAnySpot (x,y) (Empty n v) picture
- # picture = EraseRectangle (base1,base2) picture
- | n==0 = picture
- # picture = MovePenTo basenr picture
- picture = DrawString (toString n) picture
- | otherwise = picture
- where
- base = ScaleVector size (x-1, y)
- base1 = TranslatePoint base (1,-1)
- base2 = TranslatePoint base (TranslatePoint (size,~size) (-1,1))
- basenr = TranslatePoint base (2,-2)
- size = SizeArea
- DrawAnySpot pos=:(x,y) (Mine v) picture
- # picture = EraseRectangle (base1,base2) picture
- picture = FillCircle (CirclePosition pos) picture
- = picture
- where
- base = ScaleVector size (x-1, y)
- base1 = TranslatePoint base (1,-1)
- base2 = TranslatePoint base (TranslatePoint (size,~size) (-1,1))
- size = SizeArea
-
- CirclePosition :: !Position -> Circle
- CirclePosition position
- = (center, halfsize-2)
- where
- center = TranslatePoint (neg_halfsize, neg_halfsize) (ScaleVector size position)
- size = SizeArea
- halfsize = size/2
- neg_halfsize= ~halfsize
-
- DrawGrid :: !Dimension !Picture -> Picture
- DrawGrid (col,row) picture
- # picture = MovePenTo corner1 picture
- picture = DrawLines corner1 row (size*col,0) (0,size) picture
- picture = MovePenTo corner1 picture
- picture = DrawLines corner1 col (0,size*row) (size,0) picture
- picture = MovePenTo corner2 picture
- picture = DrawLines corner2 row (size*col,0) (0,size) picture
- picture = MovePenTo corner2 picture
- picture = DrawLines corner2 col (0,size*row) (size,0) picture
- = picture
- where
- corner2 = (-1, -1)
- corner1 = (0, 0)
- size = SizeArea
-
- DrawLines :: !Position !Int !Vector !Vector !Picture -> Picture
- DrawLines base nr_lines relative to_next_base picture
- # picture = LinePen relative picture
- | nr_lines==0 = picture
- # picture = MovePenTo next_base picture
- picture = DrawLines next_base (nr_lines-1) relative to_next_base picture
- | otherwise = picture
- where
- next_base = TranslatePoint base to_next_base
-
-
- /* Functions on a Minefield:
- */
-
- SowMines :: !Int !Dimension !RandomSeed -> (!Minefield,!RandomSeed)
- SowMines nr_mines dimension=:(col,row) seed
- = (PlantMines uniqueMines dimension, newSeed)
- where
- (uniqueMines,newSeed) = UniqueMines (col*row) nr_mines [(x,y) \\ x<-[1..col], y<-[1..row]] seed
-
- UniqueMines :: !Int !Int ![Position] !RandomSeed -> (![Position], !RandomSeed)
- UniqueMines max_mines nr_mines mines seed
- | nr_mines==0 = ([],seed)
- | otherwise = ([element:uniqueMines],seed2)
- with
- (element,mines1) = GetIndex (random mod max_mines) mines
- (random, seed1) = Random seed
- (uniqueMines,seed2) = UniqueMines (max_mines-1) (nr_mines-1) mines1 seed1
-
- GetIndex :: !Int ![x] -> (!x,![x])
- GetIndex n xs = (x,before++after) where (before,[x:after]) = splitAt n xs
-
- PlantMines :: [Position] !Position -> Minefield
- PlantMines _ (0,_) = []
- PlantMines mines pos=:(col,row)
- = [PlantColMines mines pos : PlantMines mines (col-1,row)]
- where
- PlantColMines :: [Position] !Position -> [Spot]
- PlantColMines _ (_,0) = []
- PlantColMines mines pos=:(col,row)
- = [PlantMine mines pos : PlantColMines mines (col,row-1)]
- where
- PlantMine :: ![Position] !Position -> Spot
- PlantMine mines pos
- | isMember pos mines = Mine Invisible
- | otherwise = Empty (CountNeighbourMines mines pos) Invisible
- where
- CountNeighbourMines :: ![Position] !Position -> Int
- CountNeighbourMines [mine:mines] pos
- | IsNeighbour mine pos = neighbours+1
- | otherwise = neighbours
- where
- neighbours = CountNeighbourMines mines pos
-
- IsNeighbour :: !Position !Position -> Bool
- IsNeighbour (x,y) (x`,y`)
- | dx==0 = dy==1
- | dx==1 = dy<=1
- | otherwise = False
- where
- dx = abs (x-x`)
- dy = abs (y-y`)
- CountNeighbourMines _ _ = 0
-
- GetSpot :: !Position !Minefield -> Spot
- GetSpot (col,row) minefield = minefield!!(col-1)!!(row-1)
-
- RevealSpot :: !Position !Minefield -> (!Spot,!Minefield)
- RevealSpot (col,row) [col_mines : minefield]
- | col==1 = (spot, [col : minefield])
- with
- (spot,col) = ColRevealSpot row col_mines
-
- ColRevealSpot :: !Int ![Spot] -> (!Spot,![Spot])
- ColRevealSpot 1 [Empty n Invisible:spots]
- = (spot, [spot:spots])
- where
- spot = Empty n Visible
- ColRevealSpot 1 l=:[spot:_]
- = (spot, l)
- ColRevealSpot n [spot:spots]
- = (spot1, [spot:spots1])
- where
- (spot1, spots1) = ColRevealSpot (n-1) spots
- ColRevealSpot _ _
- = abort "Error in rule ColRevealSpot (module MineTypes): invalid index"
- | otherwise = (spot, [col_mines : minefield`])
- with
- (spot, minefield`)= RevealSpot (col-1, row) minefield
- RevealSpot _ _ = abort "Error in rule RevealSpot (module MineTypes): invalid Position"
-
-
- /* Functions on Spots:
- */
-
- NulSpot :: !Spot -> Bool
- NulSpot (Empty 0 _) = True
- NulSpot _ = False
-
- MineSpot :: !Spot -> Bool
- MineSpot (Mine _) = True
- MineSpot _ = False
-
- InvisibleSpot :: !Spot -> Bool
- InvisibleSpot (Empty _ Visible) = False
- InvisibleSpot _ = True
-
-
- /* Functions on Pebbles:
- */
-
- RemovePebble :: !Position !Pebbles -> Pebbles
- RemovePebble pos=:(p,q) [pebble=:(x,y):pebbles]
- | p==x && q==y = pebbles
- | otherwise = [pebble:RemovePebble pos pebbles]
- RemovePebble _ _ = []
-
-
- /* Dimension defining functions:
- */
-
- WindowPictDomain :: !Dimension -> PictureDomain
- WindowPictDomain (col,row)
- = ((0,0), (max (DomainWidth col) (DomainWidth 8),max (DomainHeight row) (DomainHeight 8)))
-
- DomainWidth :: !Int -> Int
- DomainWidth col = (col+1)*SizeArea+90
-
- DomainHeight :: !Int -> Int
- DomainHeight row = row*SizeArea+1
-
- MaxDimension :: Dimension
- MaxDimension = ((maxw-90)/SizeArea-1,(maxh-1)/SizeArea)
- where
- (maxw,maxh) = MaxFixedWindowSize
-
- ScaleVector :: !Int !Vector -> Vector
- ScaleVector k (wx,wy) = (k*wx, k*wy)
-
- TranslatePoint :: !Point !Vector -> Point
- TranslatePoint (px,py) (vx,vy) = (px+vx,py+vy)
-